
#ifndef FRUSTUM_H
#define FRUSTUM_H

#include <stdint.h>
#include "../core/vmath.h"

struct room_s;
struct camera_s;
struct obb_s;


typedef struct portal_s
{
    uint16_t        vertex_count;
    uint16_t        unused;
    float          *vertex;                                                     // portal polygon vertices
    float           norm[4];                                                    // portal plane
    float           centre[3];                                                  // portal polygon center
    struct room_s  *dest_room;                                                  // where to lead the portal
}portal_t, *portal_p;

typedef struct frustum_s
{
    uint16_t            vertex_count;                                           // frustum vertices count (are equal to clip planes count)
    uint16_t            parents_count;
    
    float              *planes;                                                 // clip planes
    float              *vertex;                                                 // frustum vertices
    float              *cam_pos;                                                ///@TODO: delete it!
    float               norm[4];                                                // main frustum clip plane (inv. plane of parent portal)

    struct frustum_s   *parent;                                                 // by who frustum was generated; parent == NULL is equal generated by camera
    struct frustum_s   *next;                                                   // next frustum in list
}frustum_t, *frustum_p;


class CFrustumManager
{
public:
    CFrustumManager(uint32_t buffer_size);
   ~CFrustumManager();
    
    void Reset();
    frustum_p PortalFrustumIntersect(struct portal_s *portal, frustum_p emitter, struct camera_s *cam);

private:
    float *Alloc(uint32_t size);
    frustum_p CreateFrustum();
    void SplitPrepare(frustum_p frustum, struct portal_s *p, frustum_p emitter);
    void GenClipPlanes(frustum_p p, struct camera_s *cam);
    int  SplitByPlane(frustum_p p, float n[4], float *buf);
    
    bool m_need_realloc;
    uint32_t m_buffer_size;
    uint32_t m_allocated;
    uint8_t *m_buffer;
};

bool Frustum_HaveParent(frustum_p parent, frustum_p frustum);
bool Frustum_IsPolyVisible(struct polygon_s *p, struct frustum_s *frustum, bool check_backface);
bool Frustum_IsAABBVisible(float bbmin[3], float bbmax[3], struct frustum_s *frustum);
bool Frustum_IsOBBVisible(struct obb_s *obb, struct frustum_s *frustum);
bool Frustum_IsOBBVisibleInFrustumList(struct obb_s *obb, struct frustum_s *frustum);


portal_p Portal_Create(unsigned int vcount);
void     Portal_Clear(portal_p p);

void Portal_Move(portal_p p, float mv[3]);
bool Portal_RayIntersect(portal_p p, float dir[3], float dot[3]);
void Portal_GenNormale(portal_p p);

#endif
